﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace SignalTable
{
    class Program
    {
        static void Main(string[] args)
        {
            
            string dataSetPath = @"../../../datasets/";
            string dataSetExtension = @"_std_sh.txt";
            //string[] DataSetNames = { "iris", "ionosphere", "clim", "image", "glass", "steel", "yacht", "building", "concrete", "crime" };

            string[] DataSetNames = { "yacht", };

            if (Directory.Exists(@"../../../results"))
                Directory.Delete(@"../../../results");
            Directory.CreateDirectory(@"../../../results");


            bool zamrazanie = false; //activation of freezing feature
            bool sprwagi = false; //activation of super weights feature
            int StepOfLicznikError = 500; // 2000 -> 4000 -> 6000 -> 8000
            bool parabola = true; // d1+d2+parabola mode
            bool d1 = true;  //d1 mode
            bool d1d2 = false; //d1+d2 mode
            bool d1d2d3 = false; //d1+d2+d3 mode           
            int numOfResults = 16;
            int numTest = 100;
            //classification
            double[] kk = { 1.5 }; //ustawianie k
            double[] nn = { 1.3 }; //ustawianie n
            double[] mm = { 1.1 }; //ustawanie m
            if (d1)
                kk[0] = 1.7; //ustawianie k

            int n1 = 1; //n1 do freezingu
            int n2 = 2; //jw
            int numEpochs = 35; 
            int[] numHidden = { 5 }; //Jezeli brak warstwy ukrytej, to ustawić numHidden = {0} !
            ////////////////////////////////////////////////


            //d1 = true; d1d2 = false; d1d2d3 = false; parabola = false; zamrazanie = false; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
           //return;

            //d1 = false; d1d2 = true; d1d2d3 = false; parabola = false; zamrazanie = false; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = true; parabola = false; zamrazanie = false; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            d1 = false; d1d2 = false; d1d2d3 = false; parabola = true; zamrazanie = false; sprwagi = false;
            RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);

            //d1 = true; d1d2 = false; d1d2d3 = false; parabola = false; zamrazanie = false; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = true; d1d2d3 = false; parabola = false; zamrazanie = false; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = true; parabola = false; zamrazanie = false; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = false; parabola = true; zamrazanie = false; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);

            //d1 = true; d1d2 = false; d1d2d3 = false; parabola = false; zamrazanie = true; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = true; d1d2d3 = false; parabola = false; zamrazanie = true; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = true; parabola = false; zamrazanie = true; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = false; parabola = true; zamrazanie = true; sprwagi = false;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);

            //d1 = true; d1d2 = false; d1d2d3 = false; parabola = false; zamrazanie = true; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = true; d1d2d3 = false; parabola = false; zamrazanie = true; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = true; parabola = false; zamrazanie = true; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);
            //d1 = false; d1d2 = false; d1d2d3 = false; parabola = true; zamrazanie = true; sprwagi = true;
            //RunTests(dataSetPath, dataSetExtension, DataSetNames, zamrazanie, sprwagi, StepOfLicznikError, parabola, d1, d1d2, d1d2d3, numOfResults, numTest, kk, nn, mm, n1, n2, numEpochs, numHidden);

       
      
        }


        private static void RunTests(string dataSetPath, string dataSetExtension, string[] DataSetNames, bool zamrazanie, bool sprwagi, int StepOfLicznikError, bool parabola, bool d1, bool d1d2, bool d1d2d3, int numOfResults, int numTest, double[] kk, double[] nn, double[] mm, int n1, int n2, int numEpochs, int[] numHidden)
        {

           // System.Threading.Thread.Sleep(25000);

            string sss = @"../../../results/wynik_";
            for (int t = 0; t < DataSetNames.Length; t++)
            {

                bool fileExists = false;
                if (File.Exists(@"../../../" + DataSetNames[t] + "_Avg.txt"))
                    fileExists = true;

                StreamWriter sw1 = new StreamWriter(@"../../../" + DataSetNames[t] + "_Avg.txt", true);
                StreamWriter sw2 = new StreamWriter(@"../../../" + DataSetNames[t] + "_StdDev.txt", true);

                if (!fileExists)
                {
                    sw1.Write("parab" + "\tfreez" + "\tn1" + "\tn2" + "\tsuperw" + "\tdataset" + "\td1" + "\td2" + "\td3");
                    for (int i = 0; i <= numOfResults; i++)
                        sw1.Write("\t" + i * StepOfLicznikError);
                    sw1.WriteLine();

                    sw2.Write("parab" + "\tfreez" + "\tn1" + "\tn2" + "\tsuperw" + "\tdataset" + "\td1" + "\td2" + "\td3");
                    for (int i = 0; i <= numOfResults; i++)
                        sw2.Write("\t" + i * StepOfLicznikError);
                    sw2.WriteLine();
                }

                sw1.Write(parabola.ToString() + "\t" + zamrazanie.ToString() + "\t" + n1 + "\t" + n2 + "\t" + sprwagi.ToString() + "\t");
                sw2.Write(parabola.ToString() + "\t" + zamrazanie.ToString() + "\t" + n1 + "\t" + n2 + "\t" + sprwagi.ToString() + "\t");

                
                
                
                double[,] DataSet;
                string headerLine;
                DataSet = Utils.LoadFile(dataSetPath + DataSetNames[t] + dataSetExtension, out headerLine);
                bool classification = false;
                if (headerLine.ToLower().EndsWith("class"))
                    classification = true;
                //else
                //{
                //    kk[0] = 1.5;
                //    nn[0] = 1.7;
                //    mm[0] = 0.7;
                //}

                bool randomweights = true; //assign random weights
                string sssc = @"../../../results/wynik_" + (classification ? "class_" : "regr_") + DateTime.Now.Ticks.ToString() + "_";
                for (int x = 0; x < numTest; x++)
                {
                    StreamWriter sw = new StreamWriter(sss + t.ToString() + "_" + x.ToString() + ".txt");
                    sw.WriteLine("k" + "\t" + "n" + "\t" + "m");
                    sw.Close();
                }

                if (parabola == false)
                {
                    if (d1 == true)
                    {
                        Parallel.For(0, numTest, x =>
                        {
                            for (int i = 0; i < kk.Length; i++)
                            {
                                NetworkNoPointers N = new NetworkNoPointers(DataSet, numHidden, numEpochs, classification, randomweights);
                                N.VSS(kk[i], 0, 0, t, x, true, true, StepOfLicznikError, sprwagi, zamrazanie, n1, n2, numOfResults);
                                //N.logE(kk[i], 0, 0, t, x);
                            }
                        });
                    }
                    else
                    {
                        if (d1d2d3 == true)
                        {
                            Parallel.For(0, numTest, x =>
                            {
                                for (int i = 0; i < kk.Length; i++)
                                {
                                    for (int j = 0; j < kk.Length; j++)
                                    {
                                        for (int k = 0; k < kk.Length; k++)
                                        {
                                            NetworkNoPointers N = new NetworkNoPointers(DataSet, numHidden, numEpochs, classification, randomweights);
                                            N.VSS(kk[i], nn[j], mm[k], t, x, false, false, StepOfLicznikError, sprwagi, zamrazanie, n1, n2, numOfResults);
                                            //N.logE(kk[i], nn[j], mm[k], t, x);
                                        }

                                    }
                                }
                            });
                        }
                        else if (d1d2 == true)
                        {
                            Parallel.For(0, numTest, x =>
                            {
                                for (int i = 0; i < kk.Length; i++)
                                {
                                    for (int j = 0; j < kk.Length; j++)
                                    {
                                        NetworkNoPointers N = new NetworkNoPointers(DataSet, numHidden, numEpochs, classification, randomweights);
                                        N.VSS(kk[i], nn[j], 0, t, x, true, false, StepOfLicznikError, sprwagi, zamrazanie, n1, n2, numOfResults);
                                        //N.logE(kk[i], nn[j], 0, t, x);
                                    }
                                }
                            });
                        }
                    }
                }
                else
                    Parallel.For(0, numTest, x =>
                    {
                        for (int i = 0; i < kk.Length; i++)
                        {
                            for (int j = 0; j < kk.Length; j++)
                            {
                                Parabola N = new Parabola(DataSet, numHidden, numEpochs, classification, randomweights);
                                N.VSS(kk[i], nn[j], t, x, StepOfLicznikError, sprwagi, zamrazanie, n1,n2,numOfResults);
                            }
                        }
                    });



                int maxK = 0;
                double ilewierszy;

                if (parabola == true)
                    ilewierszy = Math.Pow(kk.Length, 2);
                if (d1 == true)
                    ilewierszy = Math.Pow(kk.Length, 1);
                if (d1d2d3 == true)
                    ilewierszy = Math.Pow(kk.Length, 3);
                if (d1d2 == true)
                    ilewierszy = Math.Pow(kk.Length, 2);
                else
                    ilewierszy = 1;


                double[,][,] tabDane = new double[DataSetNames.Length, numTest][,];
                for (int i = 0; i < numTest; i++)
                {
                    StreamReader sr2 = new StreamReader(sss + t.ToString() + "_" + i.ToString() + ".txt");
                    sr2.ReadLine();
                    for (int j = 0; j < ilewierszy; j++)
                    {
                        string[] s = sr2.ReadLine().Split(new string[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries);
                        if (maxK < s.Length)
                            maxK = s.Length;
                    }
                    sr2.Close();
                }

                for (int i = 0; i < numTest; i++)
                {
                    tabDane[t, i] = new double[(int)ilewierszy, maxK];
                    StreamReader sr2 = new StreamReader(sss + t.ToString() + "_" + i.ToString() + ".txt");
                    sr2.ReadLine();
                    for (int j = 0; j < tabDane[t, i].GetLength(0); j++)
                    {
                        string[] s = sr2.ReadLine().Split(new string[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries);
                        for (int k = 0; k < s.Length; k++)
                        {
                            tabDane[t, i][j, k] = Convert.ToDouble(s[k]);
                        }
                    }
                    sr2.Close();
                }

                double[,] srednia = new double[(int)ilewierszy, maxK];
                int[,] Dzielnik = new int[(int)ilewierszy, maxK];
                for (int i = 0; i < srednia.GetLength(0); i++)
                {
                    for (int j = 0; j < srednia.GetLength(1); j++)
                    {
                        for (int k = 0; k < numTest; k++)
                        {

                            srednia[i, j] += tabDane[t, k][i, j];

                            Dzielnik[i, j]++;

                        }
                    }
                }




                for (int i = 0; i < Dzielnik.GetLength(0); i++)
                {
   
                        srednia[i, 0] = srednia[i, 0] / Dzielnik[i, 0];
                        sw1.Write(DataSetNames[(int)srednia[i, 0]] + "\t");
                   
                    for (int j = 1; j < Dzielnik.GetLength(1) - 1; j++)
                    {

                        srednia[i, j] = srednia[i, j] / Dzielnik[i, j];
                        sw1.Write(String.Format("{0:0.000}", srednia[i, j]) + "\t");

                    }
                    sw1.WriteLine();
                }
                sw1.Close();

                double[,] StDev = new double[srednia.GetLength(0), srednia.GetLength(1)];
                for (int i = 0; i < StDev.GetLength(0); i++)
                {
                    for (int j = 3; j < StDev.GetLength(1); j++)
                    {
                        for (int k = 0; k < numTest; k++)
                        {
                            StDev[i, j] += Math.Pow(tabDane[t, k][i, j] - srednia[i, j], 2);
                        }

                        StDev[i, j] = Math.Sqrt(StDev[i, j] / numTest);
                    }
                }

                for (int i = 0; i < StDev.GetLength(0); i++)
                {
   
                        srednia[i, 0] = srednia[i, 0];
                        sw2.Write(DataSetNames[(int)srednia[i, 0]] + "\t");
                   
                    for (int j = 1; j < StDev.GetLength(1); j++)
                    {


                        if (j < 3)
                            sw2.Write(srednia[i, j] + "\t");
                        else
                            sw2.Write(StDev[i, j] + "\t");

                    }

                    sw2.WriteLine();
                }
                sw2.Close();

                for (int i = 0; i < DataSetNames.Length; i++)
                    for (int j = 0; j < numTest; j++)
                        if (File.Exists(sss + i + "_" + j + ".txt"))
                            File.Delete(sss + i + "_" + j + ".txt");
                for (int x = 0; x < 100; x++)
                {
                    for (int j = 0; j < 5; j++)
                    {
                        for (int e = 0; e < 60; e++)
                        {
                            if (File.Exists(@"../../../results/weights_" + x + "_" + j + "_e" + e + ".txt"))
                                File.Delete(@"../../../results/weights_" + x + "_" + j + "_e" + e + ".txt");
                        }
                    }
                }
            }
        }
    }
}

